function [hdr bci]=bciReadRecorderHeader(bci,varargin)
%hdr=bciReadRecorderHeader(bci,varargin) Reads information specific to recording hardware.
%
% PURPOSE:
% Read information specific to recording hardware (e.g sampling rate etc.)
% Currently supported hardware:
% TDT
%
% INPUT:
% bci:  A bci structure holding the hardware specific definitions. See
%       bciGetParam for examples
% varargin: Additional recording system dependent parametrs.
%       They can follow the first argumen (always a bci structure as the
%       normal comma separated list. The list of possible alternatives
%       reads as follows: outer brackets komma outer brackets is a list of
%       possible arguments. The / separates alternative argumnets. ''
%       denotes an empty string and [] an emtpy matrix. E.g. default
%       accepts the empty string of the string 'retry' as the first
%       argument after the bci structure and an empty matrix or a 1 as the
%       second argument.
%       TDT: none
%       default: [''/'retry'],[[]/1]
%
% OUTPUT:
% hdr:  A structure holding hardware specific information
%       hdr.Fs: the sampling frequency. Currently the only one sampling
%       frequency is possible for all channels
%       hdr.nChans: The total number of channels tha will be acquired. A
%       sub-selection can be acquired in bciGetParam.
% bci:  A modified bci structure.
%       TDT: holds COM objects for hardware access (TDT.DA) and for
%       database server (TDT.TT) in addition the raw infos retrieved.
%
% TODO:
% Christoph: Check if the fieldtrip read_header works the way its
% implemented now
% 101201 JR wrote it

if strcmpi(bci.recordingSystem,'tdt'),
        % for the moment we ignore additional arguments. 'Retry'
        % makes only limited sense because the connection to
        % servers is set up and left open on the first call
        [hdr, bci] = readHeaderTDT(bci);
        %check if the requested blocks of channels are available
        for k=1:length(bci.TDT.blockNames2Read)
            flag=[];
            for m=1:length(hdr.params.tagName)
                flag(m)=strcmpi(bci.TDT.blockNames2Read{k},hdr.params.tagName(m,:));
                if flag(m)==1
                    bci.TDT.block2ReadIdx(k)=m;
                end
            end
            if sum(flag)==0
                error(['TDT: No match found for block name: ' bci.TDT.blockNames2Read{k}])
            end
        end
        %check if the requested channels are available in the blocks
        for k=1:length(bci.TDT.block2ReadIdx)
            tmp=ismember(bci.TDT.channels2Read{k},1:hdr.params.nChannels(bci.TDT.block2ReadIdx(k)));
            if ~(sum(tmp)==length(bci.TDT.channels2Read{k}))
                idx=find(tmp==0);
                error(['TDT: In ' bci.TDT.blockNames2Read{k} ' missing channels for reading: ' num2str(idx)]);
            end
        end
        % now make a single field hdr.Fs (check if all Fs in blocks of interest are the same are same)
        tmp=unique(hdr.Fs(bci.TDT.block2ReadIdx));
        if length(tmp)==1
            hdr.Fs=tmp;
        else
            error('TDT: Different sampling frequencies found in data blocks')
        end
        % since we got here the total number of channels to read equals the number of channels requested
        hdr.nChans=length([bci.TDT.channels2Read{:}]);
        % current acquition point for all blocks of interst the same ?
        tmp=unique(hdr.nSamples(bci.TDT.block2ReadIdx));
        if length(tmp)==1
            hdr.nSamples=tmp;
        elseif max(diff(tmp))<=(size(hdr.params.tagName,1)-1)*2 %We allow for two sample difference between data blocks and set to the highest nub
            hdr.nSamples=min(tmp);
        else
            error(['TDT: Different positions in the buffer found in data blocks' num2str(hdr.nSamples(bci.TDT.block2ReadIdx))]);
        end
        hdr.nSamp=bci.TDT.nSamples(bci.TDT.block2ReadIdx);
        % Number of trials is set to one for all blocks. we can
        % savely set it to the first
        hdr.nTrials=bci.TDT.nTrials(1);
elseif strcmpi(bci.recordingSystem,'btini'),
    hdr = BTINImex();
    hdr.nTrials = 1;
else
    % assume TCP/IP buffer
    if nargin==1
        % solve different function name problem in fieldtrip versions
        if exist('ft_read_data','file'),
            bci.param.ftReadFunc=str2func('ft_read_data');
            bci.param.ftHeaderFunc=str2func('ft_read_header');
        elseif exist('read_data','file'),
            bci.param.ftReadFunc=str2func('read_data');
            bci.param.ftHeaderFunc=str2func('read_header');
        elseif ~strcmpi(bci.recordingSystem,'tdt'),
            error('Could not locate read functions for fieldtrip buffer.');
        end
        readSucc=false;
        while ~readSucc
            try
                [hdr] = bci.param.ftHeaderFunc(bci.dataBufferName);
                readSucc=true;
            catch
                error(lasterror)
                readSucc=false;
                pause(.01);
            end
        end
    elseif nargin>1,
        % read_header is a fieldtrip function
        [hdr] = bci.param.ftHeaderFunc(bci.dataBufferName,varargin{:}); % avargin{:} creates a comma separated list. Should work the same way as if the function was called with the additiona arguments
    end
end
bci.nChan=hdr.nChans;
bci.srate=hdr.Fs;